home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / zmodem-part3-unix.shar / zm.c < prev   
C/C++ Source or Header  |  1993-10-23  |  18KB  |  900 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    04-17-89  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  *
  15.  *    This version implements ZMODEM Run Length Encoding, Comparision,
  16.  *    and variable length headers.  These features were not funded
  17.  *    by the original Telenet development contract.  This software,
  18.  *    including these features, may be freely used for non
  19.  *    commercial and educational purposes.  This software may also
  20.  *    be freely used to support file transfer operations to or from
  21.  *    licensed Omen Technology products.  Contact Omen Technology
  22.  *    for licensing for other uses.  Any programs which use part or
  23.  *    all of this software must be provided in source form with this
  24.  *    notice intact except by written permission from Omen
  25.  *    Technology Incorporated.
  26.  *
  27.  *        Omen Technology Inc        FAX: 503-621-3745
  28.  *        Post Office Box 4681
  29.  *        Portland OR 97208
  30.  *
  31.  *    Previous versions of this program (not containing the extensions
  32.  *    listed above) remain in the public domain.
  33.  *
  34.  *    This code is made available in the hope it will be useful,
  35.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  36.  *    DAMAGES OF ANY KIND.
  37.  *
  38.  */
  39.  
  40. #ifndef CANFDX
  41. #include "zmodem.h"
  42. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  43. #endif
  44.  
  45. #ifndef UNSL
  46. #define UNSL
  47. #endif
  48.  
  49.  
  50. /* Globals used by ZMODEM functions */
  51. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  52. int Rxtype;        /* Type of header received */
  53. int Rxhlen;        /* Length of header received */
  54. int Rxcount;        /* Count of data bytes received */
  55. char Rxhdr[ZMAXHLEN];    /* Received header */
  56. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  57. long Rxpos;        /* Received file position */
  58. long Txpos;        /* Transmitted file position */
  59. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  60. int Crc32t;        /* Controls 32 bit CRC being sent */
  61.             /* 1 == CRC32,  2 == CRC32 + RLE */
  62. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  63.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  64. int Usevhdrs;        /* Use variable length headers */
  65. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  66. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  67. char *Altcan;        /* Alternate canit string */
  68.  
  69. static lastsent;    /* Last char we sent */
  70. static Not8bit;        /* Seven bits seen on header */
  71.  
  72. static char *frametypes[] = {
  73.     "No Response to Error Correction Request",    /* -4 */
  74.     "No Carrier Detect",        /* -3 */
  75.     "TIMEOUT",        /* -2 */
  76.     "ERROR",        /* -1 */
  77. #define FTOFFSET 4
  78.     "ZRQINIT",
  79.     "ZRINIT",
  80.     "ZSINIT",
  81.     "ZACK",
  82.     "ZFILE",
  83.     "ZSKIP",
  84.     "ZNAK",
  85.     "ZABORT",
  86.     "ZFIN",
  87.     "ZRPOS",
  88.     "ZDATA",
  89.     "ZEOF",
  90.     "ZFERR",
  91.     "ZCRC",
  92.     "ZCHALLENGE",
  93.     "ZCOMPL",
  94.     "ZCAN",
  95.     "ZFREECNT",
  96.     "ZCOMMAND",
  97.     "ZSTDERR",
  98.     "xxxxx"
  99. #define FRTYPES 22    /* Total number of frame types in this array */
  100.             /*  not including psuedo negative entries */
  101. };
  102.  
  103. static char badcrc[] = "Bad CRC";
  104.  
  105. /* Send ZMODEM binary header hdr of type type */
  106. zsbhdr(len, type, hdr)
  107. register char *hdr;
  108. {
  109.     register int n;
  110.     register unsigned short crc;
  111.  
  112. #ifndef DSZ
  113.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  114.       frametypes[type+FTOFFSET], rclhdr(hdr));
  115. #endif
  116.     if (type == ZDATA)
  117.         for (n = Znulls; --n >=0; )
  118.             xsendline(0);
  119.  
  120.     xsendline(ZPAD); xsendline(ZDLE);
  121.  
  122.     switch (Crc32t=Txfcs32) {
  123.     case 2:
  124.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  125.         flushmo();  break;
  126.     case 1:
  127.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  128.     default:
  129.         if (Usevhdrs) {
  130.             xsendline(ZVBIN);
  131.             zsendline(len);
  132.         }
  133.         else
  134.             xsendline(ZBIN);
  135.         zsendline(type);
  136.         crc = updcrc(type, 0);
  137.  
  138.         for (n=len; --n >= 0; ++hdr) {
  139.             zsendline(*hdr);
  140.             crc = updcrc((0377& *hdr), crc);
  141.         }
  142.         crc = updcrc(0,updcrc(0,crc));
  143.         zsendline(crc>>8);
  144.         zsendline(crc);
  145.     }
  146.     if (type != ZDATA)
  147.         flushmo();
  148. }
  149.  
  150.  
  151. /* Send ZMODEM binary header hdr of type type */
  152. zsbh32(len, hdr, type, flavour)
  153. register char *hdr;
  154. {
  155.     register int n;
  156.     register UNSL long crc;
  157.  
  158.     xsendline(flavour); 
  159.     if (Usevhdrs) 
  160.         zsendline(len);
  161.     zsendline(type);
  162.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  163.  
  164.     for (n=len; --n >= 0; ++hdr) {
  165.         crc = UPDC32((0377 & *hdr), crc);
  166.         zsendline(*hdr);
  167.     }
  168.     crc = ~crc;
  169.     for (n=4; --n >= 0;) {
  170.         zsendline((int)crc);
  171.         crc >>= 8;
  172.     }
  173. }
  174.  
  175. /* Send ZMODEM HEX header hdr of type type */
  176. zshhdr(len, type, hdr)
  177. register char *hdr;
  178. {
  179.     register int n;
  180.     register unsigned short crc;
  181.  
  182. #ifndef DSZ
  183.     vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  184.       frametypes[type+FTOFFSET], rclhdr(hdr));
  185. #endif
  186.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  187.     if (Usevhdrs) {
  188.         sendline(ZVHEX);
  189.         zputhex(len);
  190.     }
  191.     else
  192.         sendline(ZHEX);
  193.     zputhex(type);
  194.     Crc32t = 0;
  195.  
  196.     crc = updcrc(type, 0);
  197.     for (n=len; --n >= 0; ++hdr) {
  198.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  199.     }
  200.     crc = updcrc(0,updcrc(0,crc));
  201.     zputhex(crc>>8); zputhex(crc);
  202.  
  203.     /* Make it printable on remote machine */
  204.     sendline(015); sendline(0212);
  205.     /*
  206.      * Uncork the remote in case a fake XOFF has stopped data flow
  207.      */
  208.     if (type != ZFIN && type != ZACK)
  209.         sendline(021);
  210.     flushmo();
  211. }
  212.  
  213. /*
  214.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  215.  */
  216. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  217. zsdata(buf, length, frameend)
  218. register char *buf;
  219. {
  220.     register unsigned short crc;
  221.  
  222. #ifndef DSZ
  223.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  224. #endif
  225.     switch (Crc32t) {
  226.     case 1:
  227.         zsda32(buf, length, frameend);  break;
  228.     case 2:
  229.         zsdar32(buf, length, frameend);  break;
  230.     default:
  231.         crc = 0;
  232.         for (;--length >= 0; ++buf) {
  233.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  234.         }
  235.         xsendline(ZDLE); xsendline(frameend);
  236.         crc = updcrc(frameend, crc);
  237.  
  238.         crc = updcrc(0,updcrc(0,crc));
  239.         zsendline(crc>>8); zsendline(crc);
  240.     }
  241.     if (frameend == ZCRCW) {
  242.         xsendline(XON);  flushmo();
  243.     }
  244. }
  245.  
  246. zsda32(buf, length, frameend)
  247. register char *buf;
  248. {
  249.     register int c;
  250.     register UNSL long crc;
  251.  
  252.     crc = 0xFFFFFFFFL;
  253.     for (;--length >= 0; ++buf) {
  254.         c = *buf & 0377;
  255.         if (c & 0140)
  256.             xsendline(lastsent = c);
  257.         else
  258.             zsendline(c);
  259.         crc = UPDC32(c, crc);
  260.     }
  261.     xsendline(ZDLE); xsendline(frameend);
  262.     crc = UPDC32(frameend, crc);
  263.  
  264.     crc = ~crc;
  265.     for (c=4; --c >= 0;) {
  266.         zsendline((int)crc);  crc >>= 8;
  267.     }
  268. }
  269.  
  270. /*
  271.  * Receive array buf of max length with ending ZDLE sequence
  272.  *  and CRC.  Returns the ending character or error code.
  273.  *  NB: On errors may store length+1 bytes!
  274.  */
  275. zrdata(buf, length)
  276. register char *buf;
  277. {
  278.     register int c;
  279.     register unsigned short crc;
  280.     register char *end;
  281.     register int d;
  282.  
  283.     switch (Crc32r) {
  284.     case 1:
  285.         return zrdat32(buf, length);
  286.     case 2:
  287.         return zrdatr32(buf, length);
  288.     }
  289.  
  290.     crc = Rxcount = 0;  end = buf + length;
  291.     while (buf <= end) {
  292.         if ((c = zdlread()) & ~0377) {
  293. crcfoo:
  294.             switch (c) {
  295.             case GOTCRCE:
  296.             case GOTCRCG:
  297.             case GOTCRCQ:
  298.             case GOTCRCW:
  299.                 crc = updcrc((d=c)&0377, crc);
  300.                 if ((c = zdlread()) & ~0377)
  301.                     goto crcfoo;
  302.                 crc = updcrc(c, crc);
  303.                 if ((c = zdlread()) & ~0377)
  304.                     goto crcfoo;
  305.                 crc = updcrc(c, crc);
  306.                 if (crc & 0xFFFF) {
  307.                     zperr(badcrc);
  308.                     return ERROR;
  309.                 }
  310.                 Rxcount = length - (end - buf);
  311. #ifndef DSZ
  312.                 vfile("zrdata: %d  %s", Rxcount,
  313.                  Zendnames[d-GOTCRCE&3]);
  314. #endif
  315.                 return d;
  316.             case GOTCAN:
  317.                 zperr("Sender Canceled");
  318.                 return ZCAN;
  319.             case TIMEOUT:
  320.                 zperr("TIMEOUT");
  321.                 return c;
  322.             default:
  323.                 garbitch(); return c;
  324.             }
  325.         }
  326.         *buf++ = c;
  327.         crc = updcrc(c, crc);
  328.     }
  329. #ifdef DSZ
  330.     garbitch(); 
  331. #else
  332.     zperr("Data subpacket too long");
  333. #endif
  334.     return ERROR;
  335. }
  336.  
  337. zrdat32(buf, length)
  338. register char *buf;
  339. {
  340.     register int c;
  341.     register UNSL long crc;
  342.     register char *end;
  343.     register int d;
  344.  
  345.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  346.     while (buf <= end) {
  347.         if ((c = zdlread()) & ~0377) {
  348. crcfoo:
  349.             switch (c) {
  350.             case GOTCRCE:
  351.             case GOTCRCG:
  352.             case GOTCRCQ:
  353.             case GOTCRCW:
  354.                 d = c;  c &= 0377;
  355.                 crc = UPDC32(c, crc);
  356.                 if ((c = zdlread()) & ~0377)
  357.                     goto crcfoo;
  358.                 crc = UPDC32(c, crc);
  359.                 if ((c = zdlread()) & ~0377)
  360.                     goto crcfoo;
  361.                 crc = UPDC32(c, crc);
  362.                 if ((c = zdlread()) & ~0377)
  363.                     goto crcfoo;
  364.                 crc = UPDC32(c, crc);
  365.                 if ((c = zdlread()) & ~0377)
  366.                     goto crcfoo;
  367.                 crc = UPDC32(c, crc);
  368.                 if (crc != 0xDEBB20E3) {
  369.                     zperr(badcrc);
  370.                     return ERROR;
  371.                 }
  372.                 Rxcount = length - (end - buf);
  373. #ifndef DSZ
  374.                 vfile("zrdat32: %d %s", Rxcount,
  375.                  Zendnames[d-GOTCRCE&3]);
  376. #endif
  377.                 return d;
  378.             case GOTCAN:
  379.                 zperr("Sender Canceled");
  380.                 return ZCAN;
  381.             case TIMEOUT:
  382.                 zperr("TIMEOUT");
  383.                 return c;
  384.             default:
  385.                 garbitch(); return c;
  386.             }
  387.         }
  388.         *buf++ = c;
  389.         crc = UPDC32(c, crc);
  390.     }
  391.     zperr("Data subpacket too long");
  392.     return ERROR;
  393. }
  394.  
  395. garbitch()
  396. {
  397.     zperr("Garbled data subpacket");
  398. }
  399.  
  400. /*
  401.  * Read a ZMODEM header to hdr, either binary or hex.
  402.  *  eflag controls local display of non zmodem characters:
  403.  *    0:  no display
  404.  *    1:  display printing characters only
  405.  *    2:  display all non ZMODEM characters
  406.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  407.  *   Otherwise return negative on error.
  408.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  409.  */
  410. zgethdr(hdr, eflag)
  411. char *hdr;
  412. {
  413.     register int c, n, cancount;
  414.  
  415.     n = Zrwindow + Effbaud;        /* Max bytes before start of frame */
  416.     Rxframeind = Rxtype = 0;
  417.  
  418. startover:
  419.     cancount = 5;
  420. again:
  421.     /* Return immediate ERROR if ZCRCW sequence seen */
  422.     switch (c = readline(Rxtimeout)) {
  423.     case RCDO:
  424.     case TIMEOUT:
  425.         goto fifi;
  426.     case CAN:
  427. gotcan:
  428.         if (--cancount <= 0) {
  429.             c = ZCAN; goto fifi;
  430.         }
  431.         switch (c = readline(1)) {
  432.         case TIMEOUT:
  433.             goto again;
  434.         case ZCRCW:
  435.             switch (readline(1)) {
  436.             case TIMEOUT:
  437.                 c = ERROR; goto fifi;
  438.             case RCDO:
  439.                 goto fifi;
  440.             default:
  441.                 goto agn2;
  442.             }
  443.         case RCDO:
  444.             goto fifi;
  445.         default:
  446.             break;
  447.         case CAN:
  448.             if (--cancount <= 0) {
  449.                 c = ZCAN; goto fifi;
  450.             }
  451.             goto again;
  452.         }
  453.     /* **** FALL THRU TO **** */
  454.     default:
  455. agn2:
  456.         if ( --n == 0) {
  457.             c = GCOUNT;  goto fifi;
  458.         }
  459.         if (eflag && ((c &= 0177) & 0140))
  460.             bttyout(c);
  461.         else if (eflag > 1)
  462.             bttyout(c);
  463. #ifdef UNIX
  464.         fflush(stderr);
  465. #endif
  466.         goto startover;
  467.     case ZPAD|0200:        /* This is what we want. */
  468.         Not8bit = c;
  469.     case ZPAD:        /* This is what we want. */
  470.         break;
  471.     }
  472.     cancount = 5;
  473. splat:
  474.     switch (c = noxrd7()) {
  475.     case ZPAD:
  476.         goto splat;
  477.     case RCDO:
  478.     case TIMEOUT:
  479.         goto fifi;
  480.     default:
  481.         goto agn2;
  482.     case ZDLE:        /* This is what we want. */
  483.         break;
  484.     }
  485.  
  486.  
  487.     Rxhlen = 4;        /* Set default length */
  488.     Rxframeind = c = noxrd7();
  489.     switch (c) {
  490.     case ZVBIN32:
  491.         if ((Rxhlen = c = readline(Rxtimeout)) < 0)
  492.             goto fifi;
  493.         if (c > ZMAXHLEN)
  494.             goto agn2;
  495.         Crc32r = 1;  c = zrbhd32(hdr); break;
  496.     case ZBIN32:
  497.         if (Usevhdrs)
  498.             goto agn2;
  499.         Crc32r = 1;  c = zrbhd32(hdr); break;
  500.     case ZVBINR32:
  501.         if ((Rxhlen = c = readline(Rxtimeout)) < 0)
  502.             goto fifi;
  503.         if (c > ZMAXHLEN)
  504.             goto agn2;
  505.         Crc32r = 2;  c = zrbhd32(hdr); break;
  506.     case ZBINR32:
  507.         if (Usevhdrs)
  508.             goto agn2;
  509.         Crc32r = 2;  c = zrbhd32(hdr); break;
  510.     case RCDO:
  511.     case TIMEOUT:
  512.         goto fifi;
  513.     case ZVBIN:
  514.         if ((Rxhlen = c = readline(Rxtimeout)) < 0)
  515.             goto fifi;
  516.         if (c > ZMAXHLEN)
  517.             goto agn2;
  518.         Crc32r = 0;  c = zrbhdr(hdr); break;
  519.     case ZBIN:
  520.         if (Usevhdrs)
  521.             goto agn2;
  522.         Crc32r = 0;  c = zrbhdr(hdr); break;
  523.     case ZVHEX:
  524.         if ((Rxhlen = c = zgethex()) < 0)
  525.             goto fifi;
  526.         if (c > ZMAXHLEN)
  527.             goto agn2;
  528.         Crc32r = 0;  c = zrhhdr(hdr); break;
  529.     case ZHEX:
  530.         if (Usevhdrs)
  531.             goto agn2;
  532.         Crc32r = 0;  c = zrhhdr(hdr); break;
  533.     case CAN:
  534.         goto gotcan;
  535.     default:
  536.         goto agn2;
  537.     }
  538.     Rxpos = hdr[ZP3] & 0377;
  539.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  540.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  541.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  542. fifi:
  543.     switch (c) {
  544.     case GOTCAN:
  545.         c = ZCAN;
  546.     /* **** FALL THRU TO **** */
  547.     case ZNAK:
  548.     case ZCAN:
  549.     case ERROR:
  550.     case TIMEOUT:
  551.     case RCDO:
  552.     case GCOUNT:
  553.         zperr("Got %s", frametypes[c+FTOFFSET]);
  554.     /* **** FALL THRU TO **** */
  555. #ifndef DSZ
  556.     default:
  557.         if (c >= -4 && c <= FRTYPES)
  558.             vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  559.               frametypes[c+FTOFFSET], Rxpos);
  560.         else
  561.             vfile("zgethdr: %d %lx", c, Rxpos);
  562. #endif
  563.     }
  564.     /* Use variable length headers if we got one */
  565.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  566.         Usevhdrs = 1;
  567.     return c;
  568. }
  569.  
  570. /* Receive a binary style header (type and position) */
  571. zrbhdr(hdr)
  572. register char *hdr;
  573. {
  574.     register int c, n;
  575.     register unsigned short crc;
  576.  
  577.     if ((c = zdlread()) & ~0377)
  578.         return c;
  579.     Rxtype = c;
  580.     crc = updcrc(c, 0);
  581.  
  582.     for (n=Rxhlen; --n >= 0; ++hdr) {
  583.         if ((c = zdlread()) & ~0377)
  584.             return c;
  585.         crc = updcrc(c, crc);
  586.         *hdr = c;
  587.     }
  588.     if ((c = zdlread()) & ~0377)
  589.         return c;
  590.     crc = updcrc(c, crc);
  591.     if ((c = zdlread()) & ~0377)
  592.         return c;
  593.     crc = updcrc(c, crc);
  594.     if (crc & 0xFFFF) {
  595.         zperr(badcrc);
  596.         return ERROR;
  597.     }
  598. #ifdef ZMODEM
  599.     Protocol = ZMODEM;
  600. #endif
  601.     Zmodem = 1;
  602.     return Rxtype;
  603. }
  604.  
  605. /* Receive a binary style header (type and position) with 32 bit FCS */
  606. zrbhd32(hdr)
  607. register char *hdr;
  608. {
  609.     register int c, n;
  610.     register UNSL long crc;
  611.  
  612.     if ((c = zdlread()) & ~0377)
  613.         return c;
  614.     Rxtype = c;
  615.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  616. #ifdef DEBUGZ
  617.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  618. #endif
  619.  
  620.     for (n=Rxhlen; --n >= 0; ++hdr) {
  621.         if ((c = zdlread()) & ~0377)
  622.             return c;
  623.         crc = UPDC32(c, crc);
  624.         *hdr = c;
  625. #ifdef DEBUGZ
  626.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  627. #endif
  628.     }
  629.     for (n=4; --n >= 0;) {
  630.         if ((c = zdlread()) & ~0377)
  631.             return c;
  632.         crc = UPDC32(c, crc);
  633. #ifdef DEBUGZ
  634.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  635. #endif
  636.     }
  637.     if (crc != 0xDEBB20E3) {
  638.         zperr(badcrc);
  639.         return ERROR;
  640.     }
  641. #ifdef ZMODEM
  642.     Protocol = ZMODEM;
  643. #endif
  644.     Zmodem = 1;
  645.     return Rxtype;
  646. }
  647.  
  648.  
  649. /* Receive a hex style header (type and position) */
  650. zrhhdr(hdr)
  651. char *hdr;
  652. {
  653.     register int c;
  654.     register unsigned short crc;
  655.     register int n;
  656.  
  657.     if ((c = zgethex()) < 0)
  658.         return c;
  659.     Rxtype = c;
  660.     crc = updcrc(c, 0);
  661.  
  662.     for (n=Rxhlen; --n >= 0; ++hdr) {
  663.         if ((c = zgethex()) < 0)
  664.             return c;
  665.         crc = updcrc(c, crc);
  666.         *hdr = c;
  667.     }
  668.     if ((c = zgethex()) < 0)
  669.         return c;
  670.     crc = updcrc(c, crc);
  671.     if ((c = zgethex()) < 0)
  672.         return c;
  673.     crc = updcrc(c, crc);
  674.     if (crc & 0xFFFF) {
  675.         zperr(badcrc); return ERROR;
  676.     }
  677.     switch ( c = readline(1)) {
  678.     case 0215:
  679.         Not8bit = c;
  680.         /* **** FALL THRU TO **** */
  681.     case 015:
  682.          /* Throw away possible cr/lf */
  683.         switch (c = readline(1)) {
  684.         case 012:
  685.             Not8bit |= c;
  686.         }
  687.     }
  688. #ifdef ZMODEM
  689.     Protocol = ZMODEM;
  690. #endif
  691.     Zmodem = 1; return Rxtype;
  692. }
  693.  
  694. /* Send a byte as two hex digits */
  695. zputhex(c)
  696. register int c;
  697. {
  698.     static char    digits[]    = "0123456789abcdef";
  699.  
  700. #ifdef DEBUGZ
  701.     if (Verbose>8)
  702.         vfile("zputhex: %02X", c);
  703. #endif
  704.     sendline(digits[(c&0xF0)>>4]);
  705.     sendline(digits[(c)&0xF]);
  706. }
  707.  
  708. /*
  709.  * Send character c with ZMODEM escape sequence encoding.
  710.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  711.  */
  712. zsendline(c)
  713. {
  714.  
  715.     /* Quick check for non control characters */
  716.     if (c & 0140)
  717.         xsendline(lastsent = c);
  718.     else {
  719.         switch (c &= 0377) {
  720.         case ZDLE:
  721.             xsendline(ZDLE);
  722.             xsendline (lastsent = (c ^= 0100));
  723.             break;
  724.         case 015:
  725.         case 0215:
  726.             if (!Zctlesc && (lastsent & 0177) != '@')
  727.                 goto sendit;
  728.         /* **** FALL THRU TO **** */
  729.         case 020:
  730.         case 021:
  731.         case 023:
  732.         case 0220:
  733.         case 0221:
  734.         case 0223:
  735.             xsendline(ZDLE);
  736.             c ^= 0100;
  737.     sendit:
  738.             xsendline(lastsent = c);
  739.             break;
  740.         default:
  741.             if (Zctlesc && ! (c & 0140)) {
  742.                 xsendline(ZDLE);
  743.                 c ^= 0100;
  744.             }
  745.             xsendline(lastsent = c);
  746.         }
  747.     }
  748. }
  749.  
  750. /* Decode two lower case hex digits into an 8 bit byte value */
  751. zgethex()
  752. {
  753.     register int c;
  754.  
  755.     c = zgeth1();
  756. #ifdef DEBUGZ
  757.     if (Verbose>8)
  758.         vfile("zgethex: %02X", c);
  759. #endif
  760.     return c;
  761. }
  762. zgeth1()
  763. {
  764.     register int c, n;
  765.  
  766.     if ((c = noxrd7()) < 0)
  767.         return c;
  768.     n = c - '0';
  769.     if (n > 9)
  770.         n -= ('a' - ':');
  771.     if (n & ~0xF)
  772.         return ERROR;
  773.     if ((c = noxrd7()) < 0)
  774.         return c;
  775.     c -= '0';
  776.     if (c > 9)
  777.         c -= ('a' - ':');
  778.     if (c & ~0xF)
  779.         return ERROR;
  780.     c += (n<<4);
  781.     return c;
  782. }
  783.  
  784. /*
  785.  * Read a byte, checking for ZMODEM escape encoding
  786.  *  including CAN*5 which represents a quick abort
  787.  */
  788. zdlread()
  789. {
  790.     register int c;
  791.  
  792. again:
  793.     /* Quick check for non control characters */
  794.     if ((c = readline(Rxtimeout)) & 0140)
  795.         return c;
  796.     switch (c) {
  797.     case ZDLE:
  798.         break;
  799.     case 023:
  800.     case 0223:
  801.     case 021:
  802.     case 0221:
  803.         goto again;
  804.     default:
  805.         if (Zctlesc && !(c & 0140)) {
  806.             goto again;
  807.         }
  808.         return c;
  809.     }
  810. again2:
  811.     if ((c = readline(Rxtimeout)) < 0)
  812.         return c;
  813.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  814.         return c;
  815.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  816.         return c;
  817.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  818.         return c;
  819.     switch (c) {
  820.     case CAN:
  821.         return GOTCAN;
  822.     case ZCRCE:
  823.     case ZCRCG:
  824.     case ZCRCQ:
  825.     case ZCRCW:
  826.         return (c | GOTOR);
  827.     case ZRUB0:
  828.         return 0177;
  829.     case ZRUB1:
  830.         return 0377;
  831.     case 023:
  832.     case 0223:
  833.     case 021:
  834.     case 0221:
  835.         goto again2;
  836.     default:
  837.         if (Zctlesc && ! (c & 0140)) {
  838.             goto again2;
  839.         }
  840.         if ((c & 0140) ==  0100)
  841.             return (c ^ 0100);
  842.         break;
  843.     }
  844.     if (Verbose>1)
  845.         zperr("Bad escape sequence %x", c);
  846.     return ERROR;
  847. }
  848.  
  849. /*
  850.  * Read a character from the modem line with timeout.
  851.  *  Eat parity, XON and XOFF characters.
  852.  */
  853. noxrd7()
  854. {
  855.     register int c;
  856.  
  857.     for (;;) {
  858.         if ((c = readline(Rxtimeout)) < 0)
  859.             return c;
  860.         switch (c &= 0177) {
  861.         case XON:
  862.         case XOFF:
  863.             continue;
  864.         default:
  865.             if (Zctlesc && !(c & 0140))
  866.                 continue;
  867.         case '\r':
  868.         case '\n':
  869.         case ZDLE:
  870.             return c;
  871.         }
  872.     }
  873. }
  874.  
  875. /* Store long integer pos in Txhdr */
  876. stohdr(pos)
  877. long pos;
  878. {
  879.     Txhdr[ZP0] = pos;
  880.     Txhdr[ZP1] = pos>>8;
  881.     Txhdr[ZP2] = pos>>16;
  882.     Txhdr[ZP3] = pos>>24;
  883. }
  884.  
  885. /* Recover a long integer from a header */
  886. long
  887. rclhdr(hdr)
  888. register char *hdr;
  889. {
  890.     register long l;
  891.  
  892.     l = (hdr[ZP3] & 0377);
  893.     l = (l << 8) | (hdr[ZP2] & 0377);
  894.     l = (l << 8) | (hdr[ZP1] & 0377);
  895.     l = (l << 8) | (hdr[ZP0] & 0377);
  896.     return l;
  897. }
  898.  
  899. /* End of zm.c */
  900.